//
//  lm_conf_video_wrapper.m
//  LMConf_ios
//
//  Created by lh Authors on 16/6/19.
//  Copyright © 2016 lh. All rights reserved.
//

#import "lm_conf_video_wrapper.h"

void CALLBACK FuncVideoOnDisconnectVideoServerCB(int result, void* clientdata) {
    ConfVideoWrapper* wrapper = (__bridge ConfVideoWrapper*)(clientdata);
    for(id obj in [wrapper delegate_array]) {
        id<ConfVideoWrapperDelegate> delegate = obj;
        if([delegate respondsToSelector:@selector(onDisconnectVideoServer:)]) {
            [delegate onDisconnectVideoServer:result];
        }
    }
}

void CALLBACK FuncVideoOnAddLocalPreviewCB(
                                           int id_device, int id_preview, uint64_t context, int error, void* clientdata) {
    ConfVideoWrapper* wrapper = (__bridge ConfVideoWrapper*)(clientdata);
    for(id obj in [wrapper delegate_array]) {
        id<ConfVideoWrapperDelegate> delegate = obj;
        if([delegate respondsToSelector:@selector(onAddLocalPreview:idPreview:context:error:)]) {
            [delegate onAddLocalPreview:id_device idPreview:id_preview context:context error:error];
        }
    }
}

void CALLBACK FuncVideoOnVideoDeviceChangedCB(
                                              int change_device, int is_add, int devnums, int main_dev_id, void* clientdata) {
    ConfVideoWrapper* wrapper = (__bridge ConfVideoWrapper*)(clientdata);
    for(id obj in [wrapper delegate_array]) {
        id<ConfVideoWrapperDelegate> delegate = obj;
        if([delegate respondsToSelector:@selector(onVideoDeviceChanged:isAdd:devNums:mainDevId:)]) {
            [delegate onVideoDeviceChanged:change_device isAdd:!!is_add devNums:devnums mainDevId:main_dev_id];
        }
    }
}

void CALLBACK FuncVideoOnLocalVideoResolutionChangedCB(
                                                       int id_device, int id_preview, int width, int height, void* clientdata) {
    ConfVideoWrapper* wrapper = (__bridge ConfVideoWrapper*)(clientdata);
    for(id obj in [wrapper delegate_array]) {
        id<ConfVideoWrapperDelegate> delegate = obj;
        if([delegate respondsToSelector:@selector(onLocalVideoResolutionChanged:idPreview:width:height:)]) {
            [delegate onLocalVideoResolutionChanged:id_device idPreview:id_preview width:width height:height];
        }
    }
}

void CALLBACK FuncVideoOnRemoteVideoResolutionChangedCB(
                                                        const char* account, int id_device, int id_preview, int width, int height, void* clientdata) {
    ConfVideoWrapper* wrapper = (__bridge ConfVideoWrapper*)(clientdata);
    for(id obj in [wrapper delegate_array]) {
        id<ConfVideoWrapperDelegate> delegate = obj;
        if([delegate respondsToSelector:@selector(onRemoteVideoResolutionChanged:DevId:idPreview:width:height:)]) {
            [delegate onRemoteVideoResolutionChanged:[NSString stringWithUTF8String:account] DevId:id_device idPreview:id_preview width:width height:height];
        }
    }
}

@implementation ConfVideoWrapper

@synthesize delegate_array = delegate_array_;

- (id)init {
    if ((self = [super init])) {
        c_object_ = NULL;
        delegate_array_ = [[NSMutableArray alloc] init];
    }
    return self;
}

- (id)initWithCObject:(native_object_t)c_object {
    if ((self = [super init])) {
        c_object_ = c_object;
        delegate_array_ = [[NSMutableArray alloc] init];
        
        struct ConfVideoCallback cb;
        memset(&cb, 0, sizeof(cb));
        cb.client_data_ = (__bridge void*)self;
        cb.OnAddLocalPreview_ = FuncVideoOnAddLocalPreviewCB;
        cb.OnVideoDeviceChanged_ = FuncVideoOnVideoDeviceChangedCB;
        cb.OnDisconnectVideoServer_ = FuncVideoOnDisconnectVideoServerCB;
        cb.OnRemoteVideoResolutionChanged_ = FuncVideoOnRemoteVideoResolutionChangedCB;
        cb.OnLocalVideoResolutionChanged_ = FuncVideoOnLocalVideoResolutionChangedCB;
        lm_conf_video_set_callback(c_object_, &cb);
    }
    return self;
}

- (void)addDelegate:(id<ConfVideoWrapperDelegate>)video_delegate {
    [delegate_array_ addObject:video_delegate];
}

- (void)removeDelegate:(id<ConfVideoWrapperDelegate>)video_delegate {
    [delegate_array_ removeObject:video_delegate];
}

- (int)addLocalPreview:(DeviceIdentity)id_device
               windows:(PlatformView *)windows
               context:(uint64_t)context
               z_order:(unsigned int)z_order
                  left:(float)left
                   top:(float)top
                 right:(float)right
                bottom:(float)bottom
            id_preview:(int *)id_preview {
    return lm_conf_video_AddLocalPreview(c_object_,
                                         id_device, (__bridge void*)windows, context, z_order, left, top, right, bottom, id_preview);
}

- (int)configureLocalPreview:(DeviceIdentity)id_device
                  id_preview:(int)id_preview
                     z_order:(unsigned int)z_order
                        left:(float)left
                         top:(float)top
                       right:(float)right
                      bottom:(float)bottom {
    
    return lm_conf_video_ConfigureLocalPreview(c_object_,
                                               id_device, id_preview, z_order, left, top, right, bottom);
}

- (int)changeLocalPreviewWindow:(DeviceIdentity)id_device
                     id_preview:(int)id_preview
                        windows:(PlatformView *)windows
                        z_order:(unsigned int)z_order
                           left:(float)left
                            top:(float)top
                          right:(float)right
                         bottom:(float)bottom {
    return lm_conf_video_ChangeLocalPreviewWindow(c_object_,
                                                  id_device, id_preview, (__bridge void*)windows, z_order, left, top, right, bottom);
}

- (int)removeLocalPreview:(DeviceIdentity)id_device
               id_preview:(int)id_preview {
    return lm_conf_video_RemoveLocalPreview(c_object_,
                                            id_device, id_preview);
}

- (int)enableMirrorLocalPreview:(DeviceIdentity)id_device
                     id_preview:(int)id_preview
                         enable:(BOOL)enable
                   mirror_xaxis:(BOOL)mirror_xaxis
                   mirror_yaxis:(BOOL)mirror_yaxis {
    return lm_conf_video_EnableMirrorLocalPreview(c_object_,
                                                  id_device, id_preview, enable ? 1 : 0, mirror_xaxis ? 1 : 0, mirror_yaxis ? 1 : 0);
}

- (int)mirrorLocalPreviewState:(DeviceIdentity)id_device
                    id_preview:(int)id_preview
                        enable:(BOOL*)enable
                  mirror_xaxis:(BOOL*)mirror_xaxis
                  mirror_yaxis:(BOOL*)mirror_yaxis {
    int v1 = 0; int v2 = 0; int v3 = 0;
    int ret = lm_conf_video_MirrorLocalPreviewState(c_object_,
                                                    id_device, id_preview, &v1, &v2, &v3);
    *enable = !!v1;
    *mirror_xaxis = !!v2;
    *mirror_yaxis = !!v3;
    return ret;
}

- (int)rotateLocalPreview:(DeviceIdentity)id_device
               id_preview:(int)id_preview
                 rotation:(int)rotation {
    return lm_conf_video_RotateLocalPreview(c_object_,
                                            id_device, id_preview, rotation);
}

- (int)rotateLocalPreviewState:(DeviceIdentity)id_device
                    id_preview:(int)id_preview
                      rotation:(int*)rotation {
    return lm_conf_video_RotateLocalPreviewState(c_object_,
                                                 id_device, id_preview, rotation);
}

- (int)getLocalPreviewResolution:(DeviceIdentity)id_device
                           width:(int*)width
                          height:(int*)height {
    return lm_conf_video_GetLocalPreviewResolution(c_object_,
                                                   id_device, width, height);
}

- (int)addRemotePreview:(NSString *)account
               deviceId:(DeviceIdentity)id_device
                windows:(PlatformView *)windows
                z_order:(unsigned int)z_order
                   left:(float)left
                    top:(float)top
                  right:(float)right
                 bottom:(float)bottom
             id_preview:(int *)id_preview {
    return lm_conf_video_AddRemotePreview(c_object_,
                                          [account UTF8String], id_device, (__bridge void*)windows, z_order, left, top, right, bottom,id_preview);
}

- (int)configureRemotePreview:(NSString *)account
                     deviceId:(DeviceIdentity)id_device
                   id_preview:(int)id_preview
                      z_order:(unsigned int)z_order
                         left:(float)left
                          top:(float)top
                        right:(float)right
                       bottom:(float)bottom {
    return lm_conf_video_ConfigureRemotePreview(c_object_,
                                                [account UTF8String], id_device, id_preview, z_order, left, top, right, bottom);
}

- (int)changeRemotePreviewWindow:(NSString *)account
                        deviceId:(DeviceIdentity)id_device
                      id_preview:(int)id_preview
                         windows:(PlatformView *)windows
                         z_order:(unsigned int)z_order
                            left:(float)left
                             top:(float)top
                           right:(float)right
                          bottom:(float)bottom {
    return lm_conf_video_ChangeRemotePreviewWindow(c_object_,
                                                   [account UTF8String], id_device, id_preview, (__bridge void*)windows, z_order, left, top, right, bottom);
}

- (int)removeRemotePreview:(NSString *)account
                  deviceId:(DeviceIdentity)id_device
                id_preview:(int)id_preview {
    return lm_conf_video_RemoveRemotePreview(c_object_,
                                             [account UTF8String], id_device, id_preview);
}

- (int)enableMirrorRemotePreview:(NSString *)account
                        deviceId:(DeviceIdentity)id_device
                      id_preview:(int)id_preview
                          enable:(BOOL)enable
                    mirror_xaxis:(BOOL)mirror_xaxis
                    mirror_yaxis:(BOOL)mirror_yaxis {
    return lm_conf_video_EnableMirrorRemotePreview(c_object_, [account UTF8String],
                                                   id_device, id_preview, enable ? 1 : 0, mirror_xaxis ? 1 : 0, mirror_yaxis ? 1 : 0);
}

- (int)mirrorRemotePreviewState:(NSString *)account
                       deviceId:(DeviceIdentity)id_device
                     id_preview:(int)id_preview
                         enable:(BOOL*)enable
                   mirror_xaxis:(BOOL*)mirror_xaxis
                   mirror_yaxis:(BOOL*)mirror_yaxis {
    int v1 = 0; int v2 = 0; int v3 = 0;
    int ret = lm_conf_video_MirrorRemotePreviewState(c_object_,
                                                     [account UTF8String], id_device, id_preview, &v1, &v2, &v3);
    *enable = !!v1;
    *mirror_xaxis = !!v2;
    *mirror_yaxis = !!v3;
    return ret;
}

- (int)rotateRemotePreview:(NSString *)account
                  deviceId:(DeviceIdentity)id_device
                id_preview:(int)id_preview
                  rotation:(int)rotation {
    return lm_conf_video_RotateRemotePreview(c_object_,
                                             [account UTF8String], id_device, id_preview, rotation);
}

- (int)rotateRemotePreviewState:(NSString *)account
                       deviceId:(DeviceIdentity)id_device
                     id_preview:(int)id_preview
                       rotation:(int*)rotation {
    return lm_conf_video_RotateRemotePreviewState(c_object_,
                                                  [account UTF8String], id_device, id_preview, rotation);
}

- (int)enableRemotePreviewColorEnhancement:(NSString *)account
                                  deviceId:(DeviceIdentity)id_device
                                    enable:(BOOL)enable {
    return lm_conf_video_EnableRemotePreviewColorEnhancement(c_object_,
                                                             [account UTF8String], id_device, enable ? 1 : 0);
}

- (int)remotePreviewColorEnhancementState:(NSString *)account
                                 deviceId:(DeviceIdentity)id_device
                                   enable:(BOOL*)enable {
    int v = 0;
    int ret = lm_conf_video_RemotePreviewColorEnhancementState(c_object_,
                                                               [account UTF8String], id_device, &v);
    *enable = !!v;
    return ret;
}

- (int)enableRemotePreview:(NSString *)account
                  deviceId:(DeviceIdentity)id_device
                    enable:(BOOL)enable {
    return lm_conf_video_EnableRemotePreview(c_object_,
                                             [account UTF8String], id_device, enable ? 1 : 0);
}

- (int)getRemotePreviewState:(NSString *)account
                    deviceId:(DeviceIdentity)id_device
                      enable:(BOOL *)enable {
    int v = 0;
    int ret = lm_conf_video_GetRemotePreviewState(c_object_,
                                                  [account UTF8String], id_device, &v);
    *enable = !!v;
    return ret;
}

- (int)getRemotePreviewResolution:(NSString *)account
                         deviceId:(DeviceIdentity)id_device
                            width:(int*)width
                           height:(int*)height {
    return lm_conf_video_GetRemotePreviewResolution(c_object_,
                                                    [account UTF8String], id_device, width, height);
}

- (int)numOfDevice {
    int nums = 0;
    return lm_conf_video_NumOfDevice(c_object_, &nums);
    return nums;
}

- (int)enumDevices:(DeviceIdentity*)id_devices
              nums:(int*)nums {
    return lm_conf_video_EnumDevices(c_object_, (int*)id_devices, nums);
}

- (int)getDeviceName:(DeviceIdentity)id_device
                name:(char *)name name_len:(int)name_len
                guid:(char *)guid guid_len:(int)guid_len {
    return lm_conf_video_GetDeviceName(c_object_, id_device, name, name_len, guid, guid_len);
}

- (int)getDeviceIdWithGuid:(NSString *)guid
                  deviceId:(DeviceIdentity*)id_device {
    return lm_conf_video_GetDeviceIdWithGuid(c_object_, [guid UTF8String], (int*)(id_device));
}

- (int)getDeviceFormat:(DeviceIdentity)id_device
                pixels:(unsigned int *)pixels
                 count:(int *)count{
    return lm_conf_video_GetDeviceFormat(c_object_, id_device, pixels, count);
}

- (int)switchMobiledevicesCamera {
    return lm_conf_video_SwitchMobiledevicesCamera(c_object_);
}

- (DeviceIdentity)getMobiledevicesActiveCameraId {
    int Id = -1;
    lm_conf_video_GetMobiledevicesActiveCamera(c_object_, (int*)(&Id));
    return Id;
}

- (BOOL)isCaptureing:(DeviceIdentity)id_device {
    int v = 0;
    lm_conf_video_IsCaptureing(c_object_, id_device, &v);
    return !!v;
}

- (int)setVideoConfig:(DeviceIdentity)id_device
          videoConfig:(const struct LMVideoConfig *)config {
    return lm_conf_video_SetVideoConfig(c_object_, id_device, config);
}

- (int)getVideoConfig:(DeviceIdentity)id_device
          videoConfig:(struct LMVideoConfig *)config {
    return lm_conf_video_GetVideoConfig(c_object_, id_device, config);
}

- (int)enableDeflickering:(DeviceIdentity)id_device
                   enable:(BOOL)enable {
    return lm_conf_video_EnableDeflickering(c_object_, id_device, enable ? 1 : 0);
}

- (int)deflickeringState:(DeviceIdentity)id_device
                  enable:(BOOL*)enable {
    int v = 0;
    int ret = lm_conf_video_DeflickeringState(c_object_, id_device, &v);
    *enable = !!v;
    return ret;
}

- (int)getCaptureDeviceSnapshot:(DeviceIdentity)id_device
                       fileName:(NSString *)file_name {
    return lm_conf_video_GetCaptureDeviceSnapshot(c_object_, id_device, [file_name UTF8String]);
}

- (int)getRenderSnapshot:(NSString *)account
                deviceId:(DeviceIdentity)id_device
              id_preview:(int)id_preview
                fileName:(NSString *)file_name {
    return lm_conf_video_GetRenderSnapshot(c_object_, [account UTF8String], id_device, id_preview, [file_name UTF8String]);
}

- (int)setShowNameInVideo:(BOOL)enable {
    return lm_conf_video_SetShowNameInVideo(c_object_, enable ? 1 : 0);
}

- (BOOL)getShowNameInVideoState {
    int v = 0;
    lm_conf_video_GetShowNameInVideoState(c_object_, &v);
    return !!v;
}

- (int)enableDebugVideo:(BOOL)enable {
    return lm_conf_video_EnableDebugVideo(c_object_, enable ? 1 : 0);
}

- (BOOL)getDebugVideoState {
    int v = 0;
    lm_conf_video_GetDebugVideoState(c_object_, &v);
    return !!v;
}

- (int)getCameraType:(DeviceIdentity)id_device
          cameraType:(enum LMCameraType*)type {
    return lm_conf_video_GetCameraType(c_object_, id_device, (int*)(type));
}

- (int)addIPCamera:(const struct LMIPCameraInfo*)info
           channel:(int)channel
        mainStream:(BOOL)is_main_stream
              name:(NSString*)name {
    return lm_conf_video_AddIPCamera(c_object_, info, channel, is_main_stream ? 1 : 0, [name UTF8String]);
}

- (int)removeIPCamera:(int)identity
              channel:(int)channel
           mainStream:(BOOL)is_main_stream {
    return lm_conf_video_RemoveIPCamera(c_object_, identity, channel, is_main_stream ? 1 : 0);
}

- (int)addRAWDataCamera:(int)identity name:(NSString*)name {
    return lm_conf_video_AddRAWDataCamera(c_object_, identity, [name UTF8String]);
}

- (int)removeRAWDataCamera:(int)identity {
    return lm_conf_video_RemoveRAWDataCamera(c_object_, identity);
}

- (int)incomingRAWData:(int)identity
               rawdata:(const void*)data
                length:(size_t)data_len
                 width:(int)width
                height:(int)height
                  type:(enum LMRawVideoType)type {
    return lm_conf_video_IncomingRAWData(c_object_, identity, data, (int)data_len, width, height, type);
}

@end
